#include <windows.h>
#include <winhttp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "http_client.h"

// 错误码定义
#define HTTP_SUCCESS 0
#define HTTP_ERROR_NETWORK 1
#define HTTP_ERROR_INVALID_URL 2
#define HTTP_ERROR_REQUEST_FAILED 3
#define HTTP_ERROR_MEMORY 4

// 请求上下文结构
typedef struct {
    HttpCallback callback;
    char* url;
} RequestContext;

// 解析URL
static BOOL ParseUrl(const char* url, char** host, char** path, INTERNET_PORT* port) {
    URL_COMPONENTS urlComp;
    ZeroMemory(&urlComp, sizeof(urlComp));
    urlComp.dwStructSize = sizeof(urlComp);
    
    // 设置需要解析的字段
    urlComp.dwHostNameLength = (DWORD)-1;
    urlComp.dwUrlPathLength = (DWORD)-1;
    urlComp.dwExtraInfoLength = (DWORD)-1;
    
    if (!WinHttpCrackUrl(url, (DWORD)strlen(url), 0, &urlComp)) {
        return FALSE;
    }
    
    // 提取主机名
    *host = (char*)malloc(urlComp.dwHostNameLength + 1);
    if (!*host) return FALSE;
    memcpy(*host, urlComp.lpszHostName, urlComp.dwHostNameLength);
    (*host)[urlComp.dwHostNameLength] = '\0';
    
    // 提取路径
    *path = (char*)malloc(urlComp.dwUrlPathLength + urlComp.dwExtraInfoLength + 1);
    if (!*path) {
        free(*host);
        return FALSE;
    }
    memcpy(*path, urlComp.lpszUrlPath, urlComp.dwUrlPathLength);
    if (urlComp.dwExtraInfoLength > 0) {
        memcpy(*path + urlComp.dwUrlPathLength, urlComp.lpszExtraInfo, urlComp.dwExtraInfoLength);
    }
    (*path)[urlComp.dwUrlPathLength + urlComp.dwExtraInfoLength] = '\0';
    
    *port = urlComp.nPort;
    return TRUE;
}

// 执行HTTP请求的线程函数
static DWORD WINAPI HttpRequestThread(LPVOID lpParam) {
    RequestContext* ctx = (RequestContext*)lpParam;
    HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL;
    char* host = NULL;
    char* path = NULL;
    INTERNET_PORT port;
    BOOL bResults = FALSE;
    DWORD dwSize = 0;
    DWORD dwDownloaded = 0;
    LPSTR pszOutBuffer = NULL;
    char* response = NULL;
    DWORD responseSize = 0;
    int errorCode = HTTP_SUCCESS;
    
    // 解析URL
    if (!ParseUrl(ctx->url, &host, &path, &port)) {
        errorCode = HTTP_ERROR_INVALID_URL;
        goto cleanup;
    }
    
    // 创建会话
    hSession = WinHttpOpen(L"CRequestLib/1.0", 
                          WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                          WINHTTP_NO_PROXY_NAME, 
                          WINHTTP_NO_PROXY_BYPASS, 0);
    if (!hSession) {
        errorCode = HTTP_ERROR_NETWORK;
        goto cleanup;
    }
    
    // 设置超时（30秒）
    WinHttpSetTimeouts(hSession, 30000, 30000, 30000, 30000);
    
    // 创建连接
    wchar_t wHost[256];
    MultiByteToWideChar(CP_UTF8, 0, host, -1, wHost, 256);
    hConnect = WinHttpConnect(hSession, wHost, port, 0);
    if (!hConnect) {
        errorCode = HTTP_ERROR_NETWORK;
        goto cleanup;
    }
    
    // 创建请求
    wchar_t wPath[1024];
    MultiByteToWideChar(CP_UTF8, 0, path, -1, wPath, 1024);
    hRequest = WinHttpOpenRequest(hConnect, L"GET", wPath,
                                 NULL, WINHTTP_NO_REFERER, 
                                 WINHTTP_DEFAULT_ACCEPT_TYPES, 
                                 WINHTTP_FLAG_REFRESH);
    if (!hRequest) {
        errorCode = HTTP_ERROR_REQUEST_FAILED;
        goto cleanup;
    }
    
    // 发送请求
    bResults = WinHttpSendRequest(hRequest,
                                 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
                                 WINHTTP_NO_REQUEST_DATA, 0, 
                                 0, 0);
    if (!bResults) {
        errorCode = HTTP_ERROR_REQUEST_FAILED;
        goto cleanup;
    }
    
    // 接收响应
    bResults = WinHttpReceiveResponse(hRequest, NULL);
    if (!bResults) {
        errorCode = HTTP_ERROR_REQUEST_FAILED;
        goto cleanup;
    }
    
    // 读取响应数据
    do {
        // 检查可用数据大小
        if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) {
            errorCode = HTTP_ERROR_REQUEST_FAILED;
            break;
        }
        
        if (dwSize == 0) break;
        
        // 分配缓冲区
        pszOutBuffer = (LPSTR)malloc(dwSize + 1);
        if (!pszOutBuffer) {
            errorCode = HTTP_ERROR_MEMORY;
            break;
        }
        
        // 读取数据
        ZeroMemory(pszOutBuffer, dwSize + 1);
        if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, 
                            dwSize, &dwDownloaded)) {
            free(pszOutBuffer);
            errorCode = HTTP_ERROR_REQUEST_FAILED;
            break;
        }
        
        // 追加到响应缓冲区
        char* newResponse = (char*)realloc(response, responseSize + dwDownloaded + 1);
        if (!newResponse) {
            free(pszOutBuffer);
            errorCode = HTTP_ERROR_MEMORY;
            break;
        }
        response = newResponse;
        memcpy(response + responseSize, pszOutBuffer, dwDownloaded);
        responseSize += dwDownloaded;
        response[responseSize] = '\0';
        
        free(pszOutBuffer);
        pszOutBuffer = NULL;
        
    } while (dwSize > 0);
    
cleanup:
    // 清理资源
    if (pszOutBuffer) free(pszOutBuffer);
    if (hRequest) WinHttpCloseHandle(hRequest);
    if (hConnect) WinHttpCloseHandle(hConnect);
    if (hSession) WinHttpCloseHandle(hSession);
    if (host) free(host);
    if (path) free(path);
    
    // 调用回调函数
    if (ctx->callback) {
        if (errorCode == HTTP_SUCCESS && response) {
            ctx->callback(response, HTTP_SUCCESS);
        } else {
            ctx->callback(NULL, errorCode);
        }
    }
    
    // 清理响应数据
    if (response) free(response);
    
    // 清理上下文
    free(ctx->url);
    free(ctx);
    
    return 0;
}

// 异步GET请求函数
void http_get_async(const char* url, HttpCallback callback) {
    if (!url || !callback) return;
    
    // 创建请求上下文
    RequestContext* ctx = (RequestContext*)malloc(sizeof(RequestContext));
    if (!ctx) return;
    
    ctx->callback = callback;
    ctx->url = _strdup(url);
    if (!ctx->url) {
        free(ctx);
        return;
    }
    
    // 创建线程执行请求
    HANDLE hThread = CreateThread(NULL, 0, HttpRequestThread, ctx, 0, NULL);
    if (hThread) {
        CloseHandle(hThread);
    } else {
        // 线程创建失败，直接调用回调
        callback(NULL, HTTP_ERROR_REQUEST_FAILED);
        free(ctx->url);
        free(ctx);
    }
}
